package org.aceor.funny.common.http.executor;

import com.alibaba.fastjson.JSON;
import org.aceor.funny.common.http.retrofit.parser.HttpRequest;
import org.aceor.funny.common.http.utils.Utils;
import org.aceor.funny.common.http.utils.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.EntityBuilder;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

/**
 * Created by lxue on 15/11/19.
 */
public class HttpRequestExecutor {

    private static CloseableHttpClient client = HttpClients.createDefault();
    private static final Logger log = LoggerFactory.getLogger(HttpRequestExecutor.class);
    public static final String charset = "UTF-8";

    public static <T> T execute(HttpRequest httpRequest, Class<T> clazz) throws IOException, ClassNotFoundException {
        T response;
        HttpUriRequest request;
        switch (httpRequest.getMethod()){
            case GET:
            {
                request = new HttpGet(httpRequest.getUrl());
                RequestConfig config = RequestConfig.custom().setConnectTimeout(10*1000).setSocketTimeout(10*1000).build();
                ((HttpGet)request).setConfig(config);
                log.info("HttpGet Request Create--{}",request);
                response = HttpRequestExecutor.sendRequest(request, clazz);
                break;
            }

            case POST:
            {
                request = new HttpPost(httpRequest.getUrl());
                HttpEntity entity = null;
                /**
                 * 如果是multipart
                 */
                if(httpRequest.isMultipart()){
                    entity = EntityBuilder.create().setBinary(new byte[0]).setContentType(ContentType.APPLICATION_OCTET_STREAM).build();
                }else{
                    if(httpRequest.isFormEncoded()){
                        entity = new UrlEncodedFormEntity(Utils.convertMap2Pair(httpRequest.getData()), Charset.forName("UTF-8"));
                    }else if(httpRequest.isHasBody()){
                        String content = JSON.toJSONString(httpRequest.getObj());
                        entity = EntityBuilder.create().setText(content).setContentType(ContentType.APPLICATION_JSON).build();
                    }
                }
                ((HttpPost) request).setEntity(entity);
                RequestConfig config = RequestConfig.custom().setConnectTimeout(10*1000).setSocketTimeout(10*1000).build();
                ((HttpPost) request).setConfig(config);
                log.info("HttpPost Request Create--{}",request);
                response = HttpRequestExecutor.sendRequest(request, clazz);
                break;
            }

            default:
                throw new RuntimeException("Wrong Request Method.");
        }
        return response;
    }

    private static <T> T sendRequest(HttpUriRequest request, Class<T> clazz) throws IOException, ClassNotFoundException {
        CloseableHttpResponse response;
        T frame = null;
        InputStream is = null;

        response = client.execute(request);
        int statusCode = response.getStatusLine().getStatusCode();
        if(statusCode != HttpStatus.SC_OK){
            log.error("非正常返回,StatusCode={}",statusCode);
            throw new RuntimeException("非正常返回,StatusCode="+statusCode);
        }
        HttpEntity entity = response.getEntity();
        try {
            if (null != entity) {
                try {
                    is = entity.getContent();
                    byte[] out = IOUtils.toByteArray(is);
                    String content = new String(out,"UTF-8");
                    log.info("反序列化开始--{}",content);
                    frame = JSON.parseObject(content, clazz);
                    log.info("反序列化结束--{}",frame);
                } finally {
                    if (null != is) {
                        is.close();
                    }
                }
            } else {
                throw new RuntimeException("返回内容为空.");
            }
        }finally {
            response.close();
        }

        return frame;
    }

}
